﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management.Automation.Runspaces;
using System.Xml.Serialization;
using Broadbeach.Core.Tfs;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace Broadbeach.Core
{
    public class WorkItemChangedEventProcessor : ITfsEventProcessor
    {
        private static readonly XmlSerializer WorkItemChangedEventSerializer = new XmlSerializer(typeof(WorkItemChangedEvent));
        private readonly IScriptServerPathProvider _scriptServerPathProvider;

        public WorkItemChangedEventProcessor(IScriptServerPathProvider scriptServerPathProvider)
        {
            _scriptServerPathProvider = scriptServerPathProvider;
        }

        public void ProcessEvent(TfsTeamProjectCollection collection, string eventXml)
        {
            WorkItemChangedEvent changedEvent;
            using (var reader = new StringReader(eventXml))
            {
                changedEvent = (WorkItemChangedEvent)WorkItemChangedEventSerializer.Deserialize(reader);
            }
            var store = collection.GetService<WorkItemStore>();
            var workItemId = changedEvent.CoreFields.IntegerFields
                .Where(f => string.Equals("System.Id", f.ReferenceName, StringComparison.InvariantCultureIgnoreCase))
                .Single().NewValue;
            var wi = store.GetWorkItem(workItemId);
            ProcessInternal(changedEvent, wi, collection);
        }

        private void ProcessInternal(WorkItemChangedEvent workItemChangedEvent, WorkItem workItem, TfsTeamProjectCollection collection)
        {
            var vcs = collection.GetService<VersionControlServer>();
            var serverPath = _scriptServerPathProvider.GetScriptServerPath(collection);
            serverPath = serverPath.Replace("$(Project)", workItem.Project.Name);
            serverPath = serverPath.Replace("$(WorkItemType)", workItem.Type.Name);
            Item serverItem;
            try
            {
                serverItem = vcs.GetItem(serverPath);
            }
            catch (VersionControlException ex)
            {
                // file doesn't exist in source control
                Debug.WriteLine(ex.ToString());
                return;
            }
            var localPath = Path.Combine(Path.GetTempPath(), string.Format("{0:N}.ps1", Guid.NewGuid()));
            serverItem.DownloadFile(localPath);

            using (var space = RunspaceFactory.CreateRunspace())
            {
                space.Open();

                space.SessionStateProxy.SetVariable("WorkItem", workItem);
                space.SessionStateProxy.SetVariable("WorkItemChangedEvent", workItemChangedEvent);

                using (var pipeline = space.CreatePipeline())
                {
                    pipeline.Commands.AddScript(localPath);
                    try
                    {
                        pipeline.Invoke();
                    } 
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.ToString());
                    }
                }
            }

            File.Delete(localPath);

        }
    }
}